package com.bjpowernode.mvc.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.bjpowernode.common.client.RedisClient;
import com.bjpowernode.common.constant.RedisKey;
import com.bjpowernode.common.enums.RespCode;
import com.bjpowernode.mvc.model.result.CommonResult;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.PrintWriter;

/**
 * Token拦截器
 */
@Component("TokenInterceptor")
public class TokenInterceptor implements HandlerInterceptor {

    @Resource
    private RedisClient redisClient;

    //preHandle ： Controller方法处理之前调用
    //验证token是否有效，Redis获取存储的token
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.放行预检OPTIONS请求   request.getMethod()获取的是大写的请求方式名称
        if ("OPTIONS".equals(request.getMethod())) {
            return true;
        }

        //当请求路径为产品详情且uid为null时，即没有登录，不需要进行拦截
        String productDetailUrl = request.getContextPath() + "/product/detail";
        //request.getContextPath() 当前WEB应用的上下文路径
        //request.getRequestURI()  当前HTTP请求的URI部分(不包含域名/ip和端口号)

        if (productDetailUrl.equals(request.getRequestURI()) && request.getHeader("uid") == null) {
            return true;
        }


        boolean checkToken = false;

        //2.其他请求   获取token和uid   只有登录后才获取
        String authorization = request.getHeader("Authorization");
        //authorization不为空且以Bearer开头
        if (StrUtil.isNotBlank(authorization) && authorization.startsWith("Bearer")) {
            String token = authorization.substring(7);
            if (StrUtil.isNotBlank(token)) {
                //token不为空
                //3.从Redis中获取token对应的信息   toUpperCase将小写字符转为大写
                String key = RedisKey.TOKEN_ACCESS + token.toUpperCase();
                //System.out.println(redisClient.exists(key));
                if (redisClient.exists(key)) {
                    //key存在，验证uid是否匹配
                    //存储在Redis中的Token
                    String saveUid = redisClient.getHashField(key, "uid");
                    //请求头中的token
                    String headerUid = request.getHeader("uid");
                    if (saveUid != null && saveUid.equals(headerUid)) {
                        checkToken = true;
                    }
                }
            }
        }
        //4.验证失败，返回提示信息给前端
        if (!checkToken) {
                //自定义信息发送给前端
                CommonResult commonResult = CommonResult.warn(RespCode.TOKEN_LOGIN_INVALID);
                //1、设置HTTP响应的内容类型为"application/json;charset=UTF-8"
                response.setContentType("application/json;charset=UTF-8");
                //2、获取一个PrintWriter对象用于向响应输出流写入数据
                PrintWriter printWriter = response.getWriter();
                //3、将commonResult对象转化为JSON字符串并写入响应流
                printWriter.println(JSONUtil.toJsonStr(commonResult));
                //4、刷新输出流并关闭它
                printWriter.flush();
                printWriter.close();
        }
        return checkToken;
    }
}

